home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 August: Tool Chest / Apple_Developer_Group_August_1996_Tool_Chest.iso / Sample Code / Interapplication Communication / MenuScripter 3.1 / Sources / MSUtils.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-11-20  |  15.5 KB  |  586 lines  |  [TEXT/MPS ]

  1. /*
  2.     MSUtils.c
  3.     
  4.     Version 3.1
  5.     
  6.     Copyright © 1995 Apple Computer, Inc., all rights reserved.
  7.     
  8.     MenuScripter by Nigel Humphreys and Jon Lansdell
  9.     AppleEvent to script extensions by Greg Sutton
  10. */
  11.  
  12.  
  13.  
  14. #include <PLStringFuncs.h>
  15. #include <Events.h>
  16. #include <Traps.h>
  17. #include <Dialogs.h>
  18. #include <Fonts.h>
  19. #include <Packages.h>
  20. #include <AppleEvents.h>
  21. #include <TextUtils.h>
  22. #include "MSUtils.h"
  23.  
  24. /**-----------------------------------------------------------------------
  25.         Name:             LesserOf
  26.         Purpose:        Returns the Lesser of two longints.
  27.     -----------------------------------------------------------------------**/
  28. #pragma segment Utils
  29.         
  30. pascal long LesserOf(long A, long B)
  31.  {
  32.    if (A<B)
  33.        return(A);
  34.      else
  35.        return(B);
  36.  }   /*LesserOf*/
  37.             
  38. /**-----------------------------------------------------------------------
  39.         Name:             GreaterOf
  40.         Purpose:        Returns the Greater of two longints.
  41.     -----------------------------------------------------------------------**/
  42.     
  43. #pragma segment Utils
  44.         
  45. pascal long GreaterOf(long A, long B)
  46.  {
  47.    if (A>B)
  48.        return(A);
  49.      else
  50.        return(B);
  51.  }  /*GreaterOf*/
  52.             
  53. /**-----------------------------------------------------------------------
  54.         Name:             ShowError
  55.         Purpose:        Reports an error to the user as both string and number.
  56.     -----------------------------------------------------------------------**/
  57. #pragma segment Utils
  58.         
  59. pascal void ShowError(Str255  theError,
  60.                                           long    theErrorCode)
  61. {
  62.    short     alertResult;
  63.    Str255    theString;
  64.      OSErr     myErr;
  65.      
  66.      myErr = AEInteractWithUser(kAEDefaultTimeout, nil,nil);
  67.      
  68.      if (myErr == noErr)
  69.        {
  70.              SetCursor(&qd.arrow);
  71.              NumToString(theErrorCode, theString);
  72.              ParamText(theError, theString, (unsigned char *)"", (unsigned char *)"");
  73.              alertResult = Alert(300, nil);
  74.          }
  75. } /* ShowError */
  76.  
  77. /**-----------------------------------------------------------------------
  78.         Name:             Ours
  79.         Purpose:        Checks the frontmost window belongs to the app.
  80.     -----------------------------------------------------------------------**/
  81. #pragma segment Utils        
  82.     
  83. pascal Boolean Ours(WindowPtr aWindow)
  84.  {
  85.         if (aWindow)
  86.             if (((WindowPeek)aWindow)->windowKind == zoomDocProc)
  87.                 return(true);
  88.         return(false);
  89. } /* Ours */
  90.  
  91. /**-----------------------------------------------------------------------
  92.         Name:             SetShortMenus
  93.         Purpose:        Cuts the menus down to a minimum - Apple File Edit.
  94.                                 Greys out the unavailable options - used when no docs open
  95.     -----------------------------------------------------------------------**/
  96. #pragma segment Utils        
  97.  
  98. pascal void SetShortMenus()
  99.     DeleteMenu(mfontID);
  100.     DeleteMenu(sizeID);
  101.     DeleteMenu(styleID);
  102.     DeleteMenu(mscriptID);
  103.  
  104.     DisableItem(myMenus[fileM], fmClose);
  105.     DisableItem(myMenus[fileM], fmSave);
  106.     DisableItem(myMenus[fileM], fmSaveAs);
  107.     DisableItem(myMenus[fileM], fmRevert);
  108.     DisableItem(myMenus[fileM], fmPrint);
  109.     DisableItem(myMenus[fileM], fmPageSetUp);
  110.  
  111.     /* now the unnecessary items on the edit menu */
  112.                 
  113.     DisableItem(myMenus[editM], undoCommand);
  114.     DisableItem(myMenus[editM], cutCommand);
  115.     DisableItem(myMenus[editM], copyCommand);
  116.     DisableItem(myMenus[editM], clearCommand);
  117.     DisableItem(myMenus[editM], pasteCommand);
  118.     DisableItem(myMenus[editM], selectAllCommand);
  119.  
  120.     DrawMenuBar();
  121. }  /* SetShortMenus */
  122.  
  123. /**-----------------------------------------------------------------------
  124.         Name:             SetLongMenus
  125.         Purpose:        Reinstates the full menu bar - called when first document
  126.                     opened.
  127.     -----------------------------------------------------------------------**/
  128. #pragma segment Utils        
  129.  
  130. pascal void SetLongMenus()
  131.   {
  132.         InsertMenu(myMenus[fontM], 0);
  133.         InsertMenu(myMenus[sizeM], 0);
  134.         InsertMenu(myMenus[styleM], 0);
  135.         InsertMenu(myMenus[scriptM], 0);
  136.  
  137.         EnableItem(myMenus[fileM], fmClose);
  138.         EnableItem(myMenus[fileM], fmSave);
  139.         EnableItem(myMenus[fileM], fmSaveAs);
  140.         EnableItem(myMenus[fileM], fmRevert);
  141.         EnableItem(myMenus[fileM], fmPrint);
  142.         EnableItem(myMenus[fileM], fmPageSetUp);
  143.  
  144.         /* now the necessary items on the edit menu -
  145.             many other items fixed on each pass thru the main event
  146.             loop or before the window pulled down
  147.         */
  148.         
  149.         EnableItem(myMenus[editM], selectAllCommand);
  150.  
  151.         DrawMenuBar();
  152.     }  /* SetLongMenus */
  153.  
  154. /**-----------------------------------------------------------------------
  155.         Name:             SetStyleMenu
  156.         Purpose:        Sets the style menu checking to reflect the style of the
  157.                     first character of the current selection in the given
  158.                                 document.
  159.     -----------------------------------------------------------------------**/
  160. #pragma segment Utils        
  161.         
  162. pascal void SetStyleMenu(DPtr theDoc)
  163.   {
  164.     TextStyle        theTStyle;
  165.         short       contMode;
  166.         short       i;
  167.         
  168.         contMode = doFace;
  169.         
  170.         TEContinuousStyle(&contMode,&theTStyle,theDoc->theText);
  171.         
  172.         if ((contMode & doFace) != 0)
  173.             {
  174.                 CheckItem(myMenus[styleM], cPlain,     (theTStyle.tsFace == 0));
  175.                 CheckItem(myMenus[styleM], cBold,      (bold      & theTStyle.tsFace));
  176.                 CheckItem(myMenus[styleM], cItalic,    (italic    & theTStyle.tsFace));
  177.                 CheckItem(myMenus[styleM], cUnderline, (underline & theTStyle.tsFace));
  178.                 CheckItem(myMenus[styleM], cOutline,   (outline   & theTStyle.tsFace));
  179.                 CheckItem(myMenus[styleM], cShadow,    (shadow    & theTStyle.tsFace));
  180.                 CheckItem(myMenus[styleM], cCondense,  (condense  & theTStyle.tsFace));
  181.                 CheckItem(myMenus[styleM], cExtend,    (extend    & theTStyle.tsFace));
  182.           }
  183.         else
  184.             for (i=cPlain; i<= cExtend; i++)
  185.                 CheckItem(myMenus[styleM], i,     false);
  186.   }
  187.  
  188. /**-----------------------------------------------------------------------
  189.     Name:       SetSizeMenu
  190.     Purpose:    Outline all the items if the current font is an
  191.                 outline font. Check the size of the current selection
  192.   -----------------------------------------------------------------------**/
  193. #pragma segment Utils        
  194.  
  195. pascal void SetSizeMenu(DPtr theDoc)
  196.   {
  197.       short             i;
  198.         short                aSize;
  199.         short                max;
  200.     long                 theSize;
  201.     Str255        name;
  202.     Boolean       sizeinMenu;
  203.     Boolean       oldState;
  204.     Point         numer;
  205.     TextStyle        theStyle;
  206.         TEHandle    myText;
  207.         short       contMode;
  208.       
  209.     numer.h = 1;
  210.     numer.v = 1;
  211.  
  212.     myText = theDoc->theText;
  213.         
  214.         contMode = doSize+doFont;
  215.         
  216.         TEContinuousStyle(&contMode,&theStyle,theDoc->theText);
  217.         
  218.     sizeinMenu = false;
  219.     max = CountMItems(myMenus[sizeM]);
  220.         for (i = 1; i <= max - 5; i++)
  221.       {
  222.                 GetItem(myMenus[sizeM], i, (unsigned char *)&name);
  223.                 StringToNum(name, &theSize);
  224.                 aSize = (short)theSize;
  225.  
  226.                 if (RealFont(theStyle.tsFont, aSize) && (contMode & doFont) != 0) // there is only one font and this size exists
  227.                     SetItemStyle(myMenus[sizeM], i, outline);
  228.                 else
  229.                     SetItemStyle(myMenus[sizeM], i, 0);
  230.  
  231.                 if ((aSize == theStyle.tsSize) && (contMode & doSize) != 0)
  232.                     {
  233.                         sizeinMenu = true;
  234.                         CheckItem(myMenus[sizeM], i, true);
  235.                     }
  236.                 else
  237.                     CheckItem(myMenus[sizeM], i, false);
  238.             }
  239.         
  240.             /*
  241.                 if it's not a size in the menu,and there is only one size in the
  242.               selection range check the other item
  243.             */
  244.             
  245.             if (!sizeinMenu && (contMode & doSize) != 0)
  246.               CheckItem(myMenus[sizeM], max, true);
  247.             else
  248.                 CheckItem(myMenus[sizeM], max, false);
  249.  
  250.             /*if this is an outline font, set the rest of the items to outline style*/
  251.             /*RealFont will ensure that the sizes are outlined*/
  252.  
  253.             oldState = GetOutlinePreferred();
  254.             SetOutlinePreferred(true);
  255.             for (i = max-4; i <= max; i++)
  256.                 {
  257.                     if (IsOutline(numer, numer) && (contMode & doFont)!= 0)
  258.                         SetItemStyle(myMenus[sizeM], i, outline);
  259.                     else
  260.                         SetItemStyle(myMenus[sizeM], i, 0);
  261.                 }
  262.                 
  263.             SetOutlinePreferred(oldState);
  264.     }
  265.             
  266. /**-----------------------------------------------------------------------
  267.     Name:       SetFontMenu
  268.     Purpose:    Set the font menu according to the state of
  269.                                 current selection of the supplied document.
  270.   -----------------------------------------------------------------------**/
  271. #pragma segment Utils
  272.         
  273. pascal void SetFontMenu(DPtr theDoc)
  274.   {
  275.     MenuHandle        theMHandle;
  276.     short         theNumber;
  277.     short         i;
  278.     short                max;
  279.     Str255        name;
  280.     TextStyle     theStyle;
  281.         short         contMode;
  282.  
  283.         theMHandle = GetMHandle(mfontID);
  284.  
  285.         if (gFontMItem)
  286.       CheckItem(theMHandle, gFontMItem, false);
  287.             
  288.         max = CountMItems(theMHandle);
  289.  
  290.         contMode = doFont;
  291.         TEContinuousStyle(&contMode,&theStyle,theDoc->theText);
  292.  
  293.         gFontMItem = 0;
  294.         
  295.     if (contMode & doFont)
  296.             for (i=1; i<=max; i++)
  297.                 {
  298.                     GetItem(theMHandle, i, (unsigned char *)&name);
  299.                     GetFNum(name, &theNumber);
  300.                     if (theNumber == theStyle.tsFont)
  301.                         gFontMItem = i;
  302.                 }
  303.  
  304.     if (gFontMItem)
  305.       CheckItem(theMHandle, gFontMItem, true);
  306.             
  307.         SetSizeMenu(theDoc);
  308.         SetStyleMenu(theDoc);
  309.     }
  310.  
  311. /**-----------------------------------------------------------------------
  312.     Name:       GetTempFileName
  313.     Purpose:    Fills newstring with a temporary file name.
  314.   -----------------------------------------------------------------------**/
  315.  
  316. #pragma segment Utils
  317.  
  318. pascal void GetTempFileName(DPtr aDoc,
  319.                             Str255 newString)
  320.  
  321.     {
  322.        Str255        s;
  323.      Str255        fileName;
  324.  
  325.         if (aDoc->everSaved == false)
  326.           PLstrcpy(fileName, (unsigned char *)"\pTEXTra");
  327.         else
  328.             PLstrcpy(fileName, aDoc->theFileName);
  329.  
  330.     /*generate a unique(ish) temporary filename*/
  331.         
  332.         if (fileName[0] > 21)
  333.           fileName[0] = 21;
  334.                 
  335.         NumToString(TickCount(), s);
  336.         
  337.         PLstrcat(fileName, s);
  338.         
  339.         PLstrcpy(newString,fileName);
  340.     }
  341.  
  342. /**-----------------------------------------------------------------------
  343.     Name:       SetText
  344.     Purpose:    Sets the text of the supplied itemNo in aDialog to 
  345.                                 theString and select it.
  346.   -----------------------------------------------------------------------**/
  347.  
  348. #pragma segment Utils
  349.  
  350. pascal void SetText(DialogPtr aDialog,
  351.                     short     itemNo,
  352.                     Str255    theString)
  353.   {
  354.     Handle      itemHandle;
  355.     Rect        box;
  356.     short       kind;
  357.     TEHandle    theTEHandle;
  358.  
  359.         GetDItem(aDialog, itemNo, &kind, &itemHandle, &box);
  360.         SetIText(itemHandle, theString);
  361.         
  362.         theTEHandle = ((DialogPeek)aDialog)->textH;
  363.  
  364.         /*set all the text to be selected*/
  365.         if (theTEHandle)
  366.             TESetSelect(0, 255, theTEHandle);
  367.     }
  368.             
  369. /**-----------------------------------------------------------------------
  370.     Name:       RetrieveText
  371.     Purpose:    Returns the text of anItem in aDialog in aString.
  372.   -----------------------------------------------------------------------**/
  373.  
  374. #pragma segment Utils
  375.  
  376. pascal void RetrieveText(DialogPtr aDialog,
  377.                                                short     anItem,
  378.                                                Str255    aString)
  379.   {
  380.      short      kind;
  381.      Rect       box;
  382.      Handle     itemHandle;
  383.  
  384.          GetDItem(aDialog, anItem, &kind, &itemHandle, &box);
  385.          GetIText(itemHandle, aString);
  386.   }
  387.  
  388. /**-----------------------------------------------------------------------
  389.     Name:       DrawDefaultOutline
  390.     Purpose:    Draws an outline around theItem.
  391.                                 Called as a useritem Proc by the dialog manager.
  392.                                 To use place a useritem over the default item in the
  393.                                 dialog and install the address of this proc as the item
  394.                                 handle.
  395.   -----------------------------------------------------------------------**/
  396.  
  397. #pragma segment Utils
  398.  
  399. pascal void DrawDefaultOutline(DialogPtr theDialog, short theItem)
  400.   {
  401.       short       kind;
  402.     Handle      itemHandle;
  403.     Rect        box;
  404.                 
  405.     GetDItem(theDialog, theItem, &kind, &itemHandle, &box);
  406.     PenSize(3, 3);
  407.     InsetRect(&box, - 4, - 4);
  408.     FrameRoundRect(&box, 16, 16);
  409.     PenNormal();
  410.         
  411.     }  /* DrawDefaultOutline */
  412.             
  413. /**-----------------------------------------------------------------------
  414.     Name:       AdornDefaultButton
  415.     Purpose:    Installs DrawDefaultOutline as the useritem proc
  416.                     for the given item.
  417.   -----------------------------------------------------------------------**/
  418.  
  419. #pragma segment Utils
  420.         
  421. pascal void AdornDefaultButton(DialogPtr theDialog,short theItem)
  422.   {
  423.       short       kind;
  424.     Handle      itemHandle;
  425.     Rect        box;
  426.  
  427.         GetDItem(theDialog, theItem, &kind, &itemHandle, &box);
  428.         SetDItem(theDialog, theItem, kind, (Handle)&DrawDefaultOutline, &box);
  429.   }
  430.  
  431.     /*-------  Determining of Gestalt is available ---------------*/
  432.     /*The following routines come from the Inside Mac VI recommendations*/
  433.     /*about how to find if a trap is available*/
  434.          /*
  435.             The glue for Gestalt will be in MPW 3.2, so if it is available we will also
  436.              need to check the system version
  437.         */
  438.  
  439. pascal void GetRectOfDialogItem(DialogPtr theDialog, short theItem, Rect *theRect)
  440.     {
  441.       short       kind;
  442.     Handle      itemHandle;
  443.         
  444.         GetDItem(theDialog, theItem, &kind, &itemHandle, theRect);
  445.     }
  446.  
  447. #pragma segment Utils
  448.  
  449. pascal short NumToolboxTraps()
  450.   {
  451.         if (NGetTrapAddress(_InitGraf, ToolTrap) == NGetTrapAddress(0xAA6E, ToolTrap))
  452.             return(0x200);
  453.         else
  454.             return(0x400);
  455.     }
  456.  
  457. #pragma segment Utils
  458.  
  459. #define TrapMask  0x0800
  460.  
  461. pascal TrapType GetTrapType(short theTrap)
  462.   {
  463.         if ((theTrap & TrapMask) > 0)
  464.             return(ToolTrap);
  465.         else
  466.             return(OSTrap);
  467.     }
  468.  
  469. #pragma segment Utils
  470.  
  471. pascal Boolean TrapAvailable(short theTrap)
  472.   {
  473.         TrapType  tType;
  474.  
  475.         tType = GetTrapType(theTrap);
  476.         if (tType == ToolTrap)
  477.             {
  478.                 theTrap = theTrap & 0x07FF;
  479.                 if (theTrap >= NumToolboxTraps())
  480.                     theTrap = _Unimplemented;
  481.             }
  482.         return(NGetTrapAddress(theTrap, tType) != NGetTrapAddress(_Unimplemented,ToolTrap));
  483.     }
  484.  
  485. #pragma segment Utils
  486.  
  487. #define _Gestalt 0xA1AD
  488.  
  489. pascal Boolean GestaltAvailable()
  490.   {
  491.         return(TrapAvailable(_Gestalt));
  492.     }
  493.  
  494. /**------  FeatureIsImplemented    ------------**/
  495. /*This is called to use Gestalt to determine if a feature is implemented.
  496.  This applies to only those referenced by OSType*/
  497.  
  498. #pragma segment Utils
  499.  
  500. pascal Boolean FeatureIsImplemented(OSType  theFeature,
  501.                                                           short   theTestBit)
  502.   {
  503.     OSErr     err;
  504.     long      result;
  505.  
  506.         err = Gestalt(theFeature, &result);
  507.         if (err == noErr)
  508.             if ((result & theTestBit) == theTestBit)
  509.                 return(true);
  510.                 
  511.       return(false);
  512.     }
  513.  
  514. #pragma segment Utils
  515.  
  516. pascal Boolean CheckEnvironment()
  517.   {
  518.         /*
  519.          first determine of Gestalt is available- if it isn't exit
  520.          as we only run under 7.0.  It could it present in 6.04 - so we need
  521.          to do some further checks for important features
  522.         */
  523.  
  524.         gGestaltAvailable = GestaltAvailable();
  525.         
  526.         if (!gGestaltAvailable)
  527.             return(false);
  528.  
  529.     /*first check if the Alias manager is present*/
  530.                 
  531.         gAliasManagerImplemented  = FeatureIsImplemented(gestaltAliasMgrAttr,
  532.                                                                                                          gestaltAliasMgrPresent);
  533.             
  534.         /*check for the AppleEvents manager - we certainly can't work without it*/
  535.         
  536.         gAppleEventsImplemented   = FeatureIsImplemented(gestaltAppleEventsAttr,
  537.                                                                                                          gestaltAppleEventsPresent);
  538.             
  539.         /*check for the Outline fonts*/
  540.         
  541.         gOutlineFontsImplemented  = FeatureIsImplemented(gestaltFontMgrAttr,
  542.                                                                                                          gestaltOutlineFonts);
  543.         
  544.         return (gAliasManagerImplemented   &&
  545.                         gAppleEventsImplemented    &&
  546.                         gOutlineFontsImplemented);
  547.                                 
  548.     }  /* CheckEnvironment */
  549.             
  550.     /*
  551.         DoPageSetup returns true if the page setup of the document is altered
  552.     */
  553.     
  554.     pascal Boolean DoPageSetup(DPtr theDoc)
  555.         {
  556.             Boolean result = false;
  557.                 
  558.                 if (theDoc)
  559.                     {
  560.                         PrOpen();
  561.                         result =  PrStlDialog(theDoc->thePrintSetup);
  562.                         PrClose();
  563.                     }
  564.                     
  565.                 return(result);
  566.         }  /* DoPageSetup */
  567.  
  568. /*
  569.     Name:    CtrlKeyPressed
  570.     Purpose: Returns true if control key pressed during event
  571. */
  572. pascal Boolean CtrlKeyPressed(const EventRecord *theEvent)
  573.     {
  574.         return((theEvent->modifiers & controlKey) != 0);
  575.     }
  576.     
  577. /*
  578.     Name:    OptionKeyPressed
  579.     Purpose: Returns true if option key pressed during event
  580. */
  581. pascal Boolean OptionKeyPressed(const EventRecord *theEvent)
  582.     {
  583.         return((theEvent->modifiers & optionKey) != 0);
  584.     }
  585.